#include "zqlog.h"

#include <iostream>
#include <string>
#include <sys/stat.h>
#include <ctime>
#include <sys/timeb.h>
#include <fstream>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include "boost/make_shared.hpp"

#ifdef WIN32
#include <Windows.h>
#endif

using namespace std;

namespace libzq
{
	const static int MinWriteLogInterval = 15;
	ZQLog* ZQLog::_instance = nullptr;
	ZQLog& ZQLog::getInstance()
	{
		if (nullptr == _instance)
		{
			_instance = new ZQLog;
		}
		return *_instance;
	}

	void ZQLog::read_cfg(const char* path)
	{
		_log_cfg.SetUnicode();
		_log_cfg.LoadFile(path);
	}

	void ZQLog::install_plugin(ZQLogPluginImpl* plugin)
	{
		plugin->init(_log_cfg);
		_plugin_vec.insert(std::unique_ptr< ZQLogPluginImpl>(plugin));
	}

	void ZQLog::stop()
	{
		LOGI("ZQLog stop");
	}

	std::string ZQLog::level_name(ZQLogLevel level)
	{
		static std::map<ZQLogLevel, string> LEVEL_NAME =
		{
			{ZQLog_All, "ALL"},
			{ZQLog_Trace, "TRACE"},
			{ZQLog_Debug, "DEBUG"},
			{ZQLog_Info, "INFO"},
			{ZQLog_Warn, "WARN"},
			{ZQLog_Error, "ERROR"},
			{ZQLog_Fatal, "FATAL"},
			{ZQLog_Off, "OFF"},
		};
		return LEVEL_NAME[level];
	}

	ZQLogLevel ZQLog::getZQLogLevelByValue(int val)
	{
		try
		{
			return ZQLogLevel(val);
		}
		catch (std::exception&)
		{
			return ZQLog_All;
		}
	}

	ZQLog::ZQLog()
	{
	}

	ZQLog::~ZQLog()
	{
		_plugin_vec.clear();
	}

	string ZQLog::log_timestring()
	{
		struct timeb tb;
		ftime(&tb);
		struct tm now = *localtime(&tb.time);
		boost::format fmt_time("%d-%02d-%02d %02d:%02d:%02d.%03d");
		return std::move((fmt_time % (now.tm_year + 1900) % (now.tm_mon + 1) % now.tm_mday % now.tm_hour % now.tm_min % now.tm_sec % tb.millitm).str());
	}

	void ZQLog::emit(ZQLogLevel level, const string& msg)
	{
		for (auto& plugin : _plugin_vec)
		{
			plugin->emit(level, msg);
		}
	}

}